
/**
\file
Definition of the pass base class.
\author Sean Tromans
*/

#include <sun_pre_compiled.hpp>
#include <rainbow/viewport/pass/pass.hpp>
#include <boost/bind.hpp>

#if !defined(SUN_DISABLE_LUA)
#include <sun/lua/lua.hpp>
#endif

namespace rainbow
{

	namespace detail
	{
#if !defined(SUN_DISABLE_LUA)
		/**
		Wrapper class to allow lua to inherit from a pass.
		\author Sean Tromans
		*/
		class pass_wrapper :	public pass,
								public luabind::wrap_base
		{
			//
			//	Public Member Functions
			//
			public:

				/**
				Luabind seems to require this to have a constructor if it's a class. It works fine without one if it's a struct though.
				\author Sean Tromans
				*/
				pass_wrapper( )
				{
				}

				/**
				Informs the pass that all dependencies have been met and it is now time to draw.
				@param step_fraction How far between logic updates this frame is.
				\author Sean Tromans
				*/
				void draw( float step_fraction )
				{
					call<void>( "draw", step_fraction );
				}

				/**
				Comparison callback to sort draw_commands.
				/note
					Default implementation uses rainbow::pass::default_ordering.
				@param a The first decorated_draw_information to compare.
				@param b The second decorated_draw_information to compare.
				@return true if \c a should preceed \c b. false otherwise.
				\author Sean Tromans
				*/
				bool compare( decorated_draw_information const & a, decorated_draw_information const & b ) const
				{
					return call<bool>( "compare", a, b );
				}

			//
			//	Static Member Functions
			//
			public:

				/**
				Default (null) draw function if lua does not provide a specialisation.
				\author Sean Tromans
				*/
				static void default_draw( pass * /*p*/, float /*step_fraction*/ )
				{
					throw sun::lua::not_implemented_exception( "rainbow.pass.draw" );
				}

				/**
				Default (null) compare function if lua does not provide a specialisation.
				\author Sean Tromans
				*/
				static bool default_compare( pass * p, decorated_draw_information const & a, decorated_draw_information const & b )
				{
					return p->pass::compare( a, b );
				}
		};
#endif
	};

	//
	//	Public Member Functions
	//

	/**
	Adds a draw information to this pass to drawn later.
	@param command The draw information to enqueue.
	\author Sean Tromans
	*/
	void pass::enqueue( draw_information const & command )
	{
		//m_render_queue.insert( command );

		decorated_draw_information decorated_information( 0.0f, command );
		m_render_queue.insert( decorated_information );
	}

	//
	//	Protected Member Functions
	//

	/**
	Default constructor
	\author Sean Tromans
	*/
	pass::pass( )
	{
		m_render_queue = render_queue_t( boost::bind( &pass::compare, this, _1, _2 ) );
	}

	/**
	Comparison callback to sort draw_commands.
	/note
		Default implementation uses rainbow::pass::default_ordering.
	@param a The first decorated_draw_information_t to compare.
	@param b The second decorated_draw_information_t to compare.
	@return true if \c a should preceed \c b. false otherwise.
	\author Sean Tromans
	*/
	bool pass::compare( decorated_draw_information const & a, decorated_draw_information const & b ) const
	{
		return decorated_draw_information::default_ordering( a, b );
	}

	//
	//	Static Member Functions
	//

	/**
	Exposes the pass to lua.
	@param L The Lua State being initialised.
	\author Sean Tromans.
	*/
	void pass::lua_interface( lua_State * L )
	{
#if !defined(SUN_DISABLE_LUA)
		luabind::module( L, "rainbow" )
		[
			luabind::class_< pass, detail::pass_wrapper, pass_ptr >( "pass" )
				.def( luabind::constructor<>( ) )
				.def( "enqueue", &pass::enqueue )
				.def( "draw", &pass::draw, &detail::pass_wrapper::default_draw )
				.def( "compare", &pass::compare, &detail::pass_wrapper::default_compare )
		];
#else
		NMN_UNUSED( L );
#endif
	}

};

